package com.fm.base.json;

import org.apache.commons.text.StringEscapeUtils;

import java.util.Iterator;
import java.util.Map;

/**
 * @author finalmachine
 */
public class JsonUtils {
    @SuppressWarnings("unchecked")
    public static String toJson(Object json) {
        if (json instanceof Map) {
            StringBuilder buf = new StringBuilder("{");
            Iterator<Map.Entry<Object, Object>> iterator = ((Map<Object, Object>) json).entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Object, Object> entry = iterator.next();
                buf.append('"').append(entry.getKey()).append("\" : ").append(toJson(entry.getValue()));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("}");
            return buf.toString();
        } else if (json instanceof Iterable) {
            StringBuilder buf = new StringBuilder("[");
            Iterator<Object> iterator = ((Iterable) json).iterator();
            while (iterator.hasNext()) {
                buf.append(toJson(iterator.next()));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("]");
            return buf.toString();
        } else if (json != null && json.getClass().isArray()) {
            StringBuilder buf = new StringBuilder("[");
            Object[] array = (Object[]) json;
            for (int index = 0; index < array.length; ++index) {
                buf.append(toJson(array[index]));
                if (index < array.length - 1) {
                    buf.append(",");
                }
            }
            buf.append("]");
            return buf.toString();
        } else if (json instanceof JsonString || json instanceof String || json instanceof Character) {
            return '"' + json.toString() + '"';
        } else {
            return String.valueOf(json);
        }
    }

    @SuppressWarnings("unchecked")
    public static String toLiteJson(Object json) {
        if (json instanceof Map) {
            StringBuilder buf = new StringBuilder("{");
            Iterator<Map.Entry<Object, Object>> iterator = ((Map<Object, Object>) json).entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Object, Object> entry = iterator.next();
                buf.append('"').append(StringEscapeUtils.escapeJson(entry.getKey().toString())).append("\":")
                    .append(toLiteJson(entry.getValue()));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("}");
            return buf.toString();
        } else if (json instanceof Iterable) {
            StringBuilder buf = new StringBuilder("[");
            Iterator<Object> iterator = ((Iterable) json).iterator();
            while (iterator.hasNext()) {
                buf.append(toLiteJson(iterator.next()));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("]");
            return buf.toString();
        } else if (json != null && json.getClass().isArray()) {
            StringBuilder buf = new StringBuilder("[");
            Object[] array = (Object[]) json;
            for (int index = 0; index < array.length; ++index) {
                buf.append(toLiteJson(array[index]));
                if (index < array.length - 1) {
                    buf.append(",");
                }
            }
            buf.append("]");
            return buf.toString();
        } else if (json instanceof JsonString || json instanceof String || json instanceof Character) {
            return '"' + StringEscapeUtils.escapeJson(json.toString()) + '"';
        } else {
            return String.valueOf(json);
        }
    }

    public static String toFormatJson(Object object) {
        return toFormatJson(object, 0);
    }

    @SuppressWarnings("unchecked")
    private static String toFormatJson(Object object, int deepth) {
        if (object instanceof Map) {
            StringBuilder buf = new StringBuilder("{");
            Iterator<Map.Entry<Object, Object>> iterator = ((Map<Object, Object>) object).entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Object, Object> entry = iterator.next();
                buf.append("\n");
                for (int i = 0; i <= deepth; ++i) {
                    buf.append("\t");
                }
                buf.append("\"").append(entry.getKey()).append("\" : ").append(toFormatJson(entry.getValue(), deepth + 1));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("\n");
            for (int i = 0; i < deepth; ++i) {
                buf.append("\t");
            }
            buf.append("}");
            return buf.toString();
        } else if (object instanceof Iterable) {
            StringBuilder buf = new StringBuilder("[");
            Iterator<Object> iterator = ((Iterable) object).iterator();
            while (iterator.hasNext()) {
                buf.append("\n");
                for (int i = 0; i <= deepth; ++i) {
                    buf.append("\t");
                }
                buf.append(toFormatJson(iterator.next(), deepth + 1));
                if (iterator.hasNext()) {
                    buf.append(",");
                }
            }
            buf.append("\n");
            for (int i = 0; i < deepth; ++i) {
                buf.append("\t");
            }
            buf.append("]");
            return buf.toString();
        } else if (object != null && object.getClass().isArray()) {
            StringBuilder buf = new StringBuilder("[");
            Object[] array = (Object[]) object;
            for (int index = 0; index < array.length; ++index) {
                buf.append("\n");
                for (int i = 0; i <= deepth; ++i) {
                    buf.append("\t");
                }
                buf.append(toFormatJson(array[index], deepth + 1));
                if (index < array.length - 1) {
                    buf.append(",");
                }
            }
            buf.append("\n");
            for (int i = 0; i < deepth; ++i) {
                buf.append("\t");
            }
            buf.append("]");
            return buf.toString();
        } else if (object instanceof JsonString || object instanceof String || object instanceof Character) {
            return '"' + object.toString() + '"';
        } else {
            return String.valueOf(object);
        }
    }
}
